﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Parser.Helpers
{
    /// <summary>
    /// Represents a user agent string and parses it
    /// </summary>
    /// 
    /// <author>Alexander Seeliger</author>
    public class UserAgent
    {
        /// <summary>
        /// Webbrowser
        /// </summary>
        private string webbrowser;

        /// <summary>
        /// Webbrowser version
        /// </summary>
        private string webbrowserversion;

        /// <summary>
        /// Operation system
        /// </summary>
        private string operationsystem;

        /// <summary>
        /// Known names in the user agent string
        /// </summary>
        private Dictionary<string, string> os = new Dictionary<string, string>() 
        {
            { "Android"             , "AND" },
			{ "Linux"				, "LIN" },

			{ "Windows NT 6.1"		, "WI7" },
			{ "Windows 7"			, "WI7" },
			{ "Windows NT 6.0"		, "WVI" },
			{ "Windows Vista"		, "WVI" },
			{ "Windows NT 5.2"		, "WS3" },
			{ "Windows Server 2003"	, "WS3" },
			{ "Windows NT 5.1"		, "WXP" },
			{ "Windows XP"			, "WXP" },
			{ "Windows NT 5.0"		, "W2K" },
			{ "Windows 2000"		, "W2K" },
			{ "Windows NT 4.0"		, "WNT" },
			{ "WinNT"				, "WNT" },
			{ "Windows NT"			, "WNT" },
			{ "Win 9x 4.90"			, "WME" },
			{ "Windows ME"			, "WME" },
			{ "Win98"				, "W98" },
			{ "Windows 98"			, "W98" },
			{ "Win32"				, "W95" },
			{ "Win95"				, "W95" },		
			{ "Windows 95"			, "W95" },

			{ "iPod"				, "IPD" },
			{ "iPhone"				, "IPH" },
			{ "iPad"				, "IPA" },
			{ "Darwin"				, "MAC" },
			{ "Macintosh"			, "MAC" },
			{ "Power Macintosh"		, "MAC" },
			{ "Mac_PowerPC"			, "MAC" }, 
			{ "Mac PPC"				, "MAC" },
			{ "PPC"					, "MAC" },
			{ "Mac PowerPC"			, "MAC" },
			{ "Mac OS"				, "MAC" },

			{ "webOS"				, "WOS" },
			{ "Palm webOS"			, "WOS" },
			{ "PalmOS"				, "POS" },
			{ "Palm OS"				, "POS" },

			{ "BlackBerry"			, "BLB" },

			{ "SunOS"				, "SOS" },

			{ "FreeBSD"				, "BSD" },
			{ "NetBSD"				, "NBS" },
			{ "OpenBSD"				, "OBS" },

			{ "PlayStation Portable", "PSP" },
			{ "PlayStation 3"		, "PS3" }
        };

        /// <summary>
        /// Names of the operation systems
        /// </summary>
        private Dictionary<string, string> os_name = new Dictionary<string, string>()
        {
            { "WI7"                 , "Microsoft Windows 7" },
            { "WVI"                 , "Microsoft Windows Vista" },
            { "WS3"                 , "Microsoft Windows Server 2003" },
            { "WXP"                 , "Microsoft Windows XP" },
            { "W98"                 , "Microsoft Windows 98" },
            { "W2K"                 , "Microsoft Windows 2000" },
            { "WNT"                 , "Microsoft Windows NT" },
            { "WME"                 , "Microsoft Windows ME" },
            { "W95"                 , "Microsoft Windows 95" },
            { "WCE"                 , "Microsoft Windows CE" },
            { "WOS"                 , "Palm WebOS" },
            { "POS"                 , "Palm OS" },
            { "PS3"                 , "Sony Playstation 3" },
            { "PSP"                 , "Sony Playstation Portable" },
            { "IPD"                 , "Apple iPhone OS" },
            { "IPH"                 , "Apple iPhone OS" },
            { "IPA"                 , "Apple iPad OS" },
            { "MAC"                 , "Apple MAC OS X" },
            { "OBS"                 , "OpenBSD" },
            { "BSD"                 , "FreeBSD" },
            { "NBS"                 , "NetBSD" },
            { "BLB"                 , "BlackBerry" },
            { "AND"                 , "Android" },
            { "LIN"                 , "Linux" }
        };

        /// <summary>
        /// Known browser strings in user agent string
        /// </summary>
        private Dictionary<string, string> browser = new Dictionary<string, string>()
        {
			{ "android"						    , "AN" },
			{ "blackberry"					    , "BB" },

			{ "chrome"						    , "CH" },

			{ "mozilla firebird"				, "FB" },
			{ "firebird"						, "FB" },
			{ "minefield"						, "FF" },
			{ "granparadiso"					, "FF" },
			{ "iceweasel"						, "FF" },
			{ "icecat"						    , "FF" },
			{ "firefox"						    , "FF" },

			{ "flock"							, "FL" },

			{ "msie"							, "IE" },
			{ "microsoft internet explorer"	    , "IE" },
			{ "internet explorer"				, "IE" },

			{ "gnuzilla"						, "SM" },
			{ "iceape"						    , "SM" },
			{ "seamonkey"						, "SM" },

			{ "navigator"						, "NS" },
			{ "netscape6"						, "NS" },
			{ "netscape"						, "NS" },

			{ "opera"							, "OP" },

			{ "safari"						    , "SF" },

			{ "webos"							, "WO" },
        };

        /// <summary>
        /// Browser names
        /// </summary>
        private Dictionary<string, string> browser_name = new Dictionary<string, string>()
        {
            { "AN"                              , "Android" },
            { "BB"                              , "BlackBerry" },
            { "CH"                              , "Chrome" },
            { "FB"                              , "Mozilla Firebird" },
            { "FF"                              , "Mozilla Firefox" },
            { "FL"                              , "Flock" },
            { "IE"                              , "Microsoft Internet Explorer" },
            { "SM"                              , "Mozilla SeeMonkey" },
            { "NS"                              , "Netscape" },
            { "OP"                              , "Opera" },
            { "SF"                              , "Apple Safari" },
            { "WO"                              , "Palm webOS" }
        };

        /// <summary>
        /// Webbrowser
        /// </summary>
        public string Webbrowser
        {
            get
            {
                return webbrowser;
            }
            set
            {
                webbrowser = value;
            }
        }

        /// <summary>
        /// Webbrowser
        /// </summary>
        public string WebbrowserVersion
        {
            get
            {
                return webbrowserversion;
            }
            set
            {
                webbrowserversion = value;
            }
        }

        /// <summary>
        /// Operation system
        /// </summary>
        public string OperationSystem
        {
            get
            {
                return operationsystem;
            }
            set
            {
                operationsystem = value;
            }
        }

        /// <summary>
        /// Constructs a new user agent class for parsing the string
        /// </summary>
        /// <param name="useragent">User agent string</param>
        public UserAgent(string useragent)
        {
            ParseUserAgent(useragent);
        }

        /// <summary>
        /// Parses the given user agent string
        /// </summary>
        /// <param name="useragent">User agent string</param>
        private void ParseUserAgent(string useragent)
        {
            // replace + to space
            useragent = useragent.Replace("+", " ");

            GetBrowser(useragent);
            GetOperationSystem(useragent);
        }

        /// <summary>
        /// Gets the browser and browser version
        /// TODO: Better detection
        /// </summary>
        /// <param name="useragent">User agent string (formated before)</param>
        private void GetBrowser(string useragent)
        {
            string id = "";

            string browserPattern = string.Join("|", new List<string>(browser.Keys).ToArray());

            // identify the browser
            foreach (KeyValuePair<string, string> item in browser)
            {
                if (useragent.ToLower().Contains(item.Key.ToLower()))
                {
                    id = item.Value;
                }
            }

            if (id == "")
                return;

            // set the browser
            webbrowser = browser_name[id];
        }

        /// <summary>
        /// Gets the operation system
        /// </summary>
        /// <param name="useragent">User agent string (formated before)</param>
        private void GetOperationSystem(string useragent)
        {
            string id = "";

            foreach (KeyValuePair<string, string> item in os)
            {
                if (useragent.ToLower().Contains(item.Key.ToLower()))
                {
                    id = item.Value;
                    break;
                }
            }

            if (id == "")
                return;

            // set the operation system
            operationsystem = os_name[id];
        }
    }
}
